package cn.sdormitory.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.sdormitory.basedata.dao.BClassDao;
import cn.sdormitory.basedata.vo.BClassVo;
import cn.sdormitory.morningExercises.entity.MorningExercises;
import cn.sdormitory.retention.DormitoryRetention;
import cn.sdormitory.service.AppMonthlyStatisticsService;
import cn.sdormitory.service.AppMorningExercisesService;
import cn.sdormitory.service.AppRetentionService;
import cn.sdormitory.smartdor.dao.SdAttenceDao;
import cn.sdormitory.smartdor.entity.DeptDormitorySummary;
import cn.sdormitory.smartdor.entity.MonthlyStatisticsDetail;
import cn.sdormitory.smartdor.entity.SdStudentAttenceDetail;
import cn.sdormitory.sys.dao.SysDeptDao;
import cn.sdormitory.sys.dao.SysUserDao;
import cn.sdormitory.sys.entity.SysUser;
import cn.sdormitory.sys.service.SysUserRoleService;
import cn.sdormitory.violative.dao.ViolationPatrolDao;
import cn.sdormitory.violative.entity.ViolationPatrol;
import cn.sdormitory.workflow.dao.ViolationApplyDao;
import cn.sdormitory.workflow.entity.ViolationApply;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @className: AppMonthlyStatisticsServiceImpl
 * @author: Alex
 * @date: 2024/12/3
 **/
@Service
public class AppMonthlyStatisticsServiceImpl implements AppMonthlyStatisticsService {
	
	@Resource
	private SysUserDao sysUserDao;
	
	@Resource
	private SysUserRoleService sysUserRoleService;
	
	@Resource
	private SysDeptDao sysDeptDao;
	
	@Resource
	private BClassDao bClassDao;
	
	@Resource
	private SdAttenceDao sdAttenceDao;
	
	@Resource
	private ViolationApplyDao violationApplyDao;
	
	@Resource
	private AppMorningExercisesService appMorningExercisesService;
	
	@Resource
	private AppRetentionService appRetentionService;
	
	@Resource
	private ViolationPatrolDao violationPatrolDao;
	
	@Override
	public List<MonthlyStatisticsDetail> getMonthlyDeptDormitorySummary(String userId, String month, String operateType) {
		
		List<BClassVo> bClassVos = getbClassVos(userId);
		List<Long> classIds = bClassVos.stream().map(BClassVo::getClassId).collect(Collectors.toList());
		List<SdStudentAttenceDetail> dormitory = new ArrayList<>();
		
		List<MonthlyStatisticsDetail> monthlyStatisticsDetails = new ArrayList<>();
		
		if (operateType.equals("dormitory")) {
			dormitory = sdAttenceDao.getMonthlyAttenceStatisticsData(classIds, month, "2");
			Map<String, List<SdStudentAttenceDetail>> collect = dormitory.stream().collect(Collectors.groupingBy(SdStudentAttenceDetail::getClassName));
			for (BClassVo bClassVo : bClassVos) {
				MonthlyStatisticsDetail monthlyStatisticsDetail = new MonthlyStatisticsDetail();
				monthlyStatisticsDetail.setClassId(String.valueOf(bClassVo.getClassId()));
				monthlyStatisticsDetail.setClassName(bClassVo.getClassName());
				monthlyStatisticsDetail.setClassCount(0L);
				List<SdStudentAttenceDetail> studentAttenceDetails = collect.get(bClassVo.getClassName());
				if (CollectionUtil.isNotEmpty(studentAttenceDetails)) {
					monthlyStatisticsDetail.setClassCount((long) studentAttenceDetails.size());
				}
				monthlyStatisticsDetails.add(monthlyStatisticsDetail);
			}
			Collections.sort(monthlyStatisticsDetails, Comparator.comparingLong(MonthlyStatisticsDetail::getClassCount).reversed());
			return monthlyStatisticsDetails;
		}
		if (operateType.equals("weekend")) {
			dormitory = sdAttenceDao.getMonthlyWeekendStatisticsData(classIds, month, "2");
			Map<String, List<SdStudentAttenceDetail>> collect = dormitory.stream().collect(Collectors.groupingBy(SdStudentAttenceDetail::getClassName));
			for (BClassVo bClassVo : bClassVos) {
				MonthlyStatisticsDetail monthlyStatisticsDetail = new MonthlyStatisticsDetail();
				monthlyStatisticsDetail.setClassId(String.valueOf(bClassVo.getClassId()));
				monthlyStatisticsDetail.setClassName(bClassVo.getClassName());
				monthlyStatisticsDetail.setClassCount(0L);
				List<SdStudentAttenceDetail> studentAttenceDetails = collect.get(bClassVo.getClassName());
				if (CollectionUtil.isNotEmpty(studentAttenceDetails)) {
					monthlyStatisticsDetail.setClassCount((long) studentAttenceDetails.size());
				}
				monthlyStatisticsDetails.add(monthlyStatisticsDetail);
			}
			Collections.sort(monthlyStatisticsDetails, Comparator.comparingLong(MonthlyStatisticsDetail::getClassCount).reversed());
			return monthlyStatisticsDetails;
		}
		switch (operateType) {
			case "retention":
				List<DormitoryRetention> retentions =  appRetentionService.getMonthlyStatisticsRetention(classIds, month);
				Map<String, List<DormitoryRetention>> collect = retentions.stream().collect(Collectors.groupingBy(DormitoryRetention::getClassName));
				for (BClassVo bClassVo : bClassVos) {
					MonthlyStatisticsDetail monthlyStatisticsDetail = new MonthlyStatisticsDetail();
					monthlyStatisticsDetail.setClassId(String.valueOf(bClassVo.getClassId()));
					monthlyStatisticsDetail.setClassName(bClassVo.getClassName());
					monthlyStatisticsDetail.setClassCount(0L);
					List<DormitoryRetention> studentAttenceDetails = collect.get(bClassVo.getClassName());
					if (CollectionUtil.isNotEmpty(studentAttenceDetails)) {
						monthlyStatisticsDetail.setClassCount((long) studentAttenceDetails.size());
					}
					monthlyStatisticsDetails.add(monthlyStatisticsDetail);
				}
				break;
			case "morningExercises":
				List<MorningExercises> morningExercises = appMorningExercisesService.getMonthlyStatisticsMorningExercises(classIds, month);
				Map<String, List<MorningExercises>> exercises = morningExercises.stream().collect(Collectors.groupingBy(MorningExercises::getClassName));
				for (BClassVo bClassVo : bClassVos) {
					MonthlyStatisticsDetail monthlyStatisticsDetail = new MonthlyStatisticsDetail();
					monthlyStatisticsDetail.setClassId(String.valueOf(bClassVo.getClassId()));
					monthlyStatisticsDetail.setClassName(bClassVo.getClassName());
					monthlyStatisticsDetail.setClassCount(0L);
					List<MorningExercises> studentAttenceDetails = exercises.get(bClassVo.getClassName());
					if (CollectionUtil.isNotEmpty(studentAttenceDetails)) {
						monthlyStatisticsDetail.setClassCount((long) studentAttenceDetails.size());
					}
					monthlyStatisticsDetails.add(monthlyStatisticsDetail);
				}
				break;
			case "patrol":
				List<ViolationPatrol> violationPatrols = violationPatrolDao.getMonthlyViolationCount(month, classIds);
				Map<String, List<ViolationPatrol>> patrols = violationPatrols.stream().collect(Collectors.groupingBy(ViolationPatrol::getClassName));
				for (BClassVo bClassVo : bClassVos) {
					MonthlyStatisticsDetail monthlyStatisticsDetail = new MonthlyStatisticsDetail();
					monthlyStatisticsDetail.setClassId(String.valueOf(bClassVo.getClassId()));
					monthlyStatisticsDetail.setClassName(bClassVo.getClassName());
					monthlyStatisticsDetail.setClassCount(0L);
					List<ViolationPatrol> studentAttenceDetails = patrols.get(bClassVo.getClassName());
					if (CollectionUtil.isNotEmpty(studentAttenceDetails)) {
						monthlyStatisticsDetail.setClassCount((long) studentAttenceDetails.size());
					}
					monthlyStatisticsDetails.add(monthlyStatisticsDetail);
				}
				break;
			case "violation":
				List<ViolationApply> violationStatistics = violationApplyDao.getMonthlyViolationStatistics(month, classIds);
				Map<String, List<ViolationApply>> violations = violationStatistics.stream().collect(Collectors.groupingBy(ViolationApply::getClassName));
				for (BClassVo bClassVo : bClassVos) {
					MonthlyStatisticsDetail monthlyStatisticsDetail = new MonthlyStatisticsDetail();
					monthlyStatisticsDetail.setClassId(String.valueOf(bClassVo.getClassId()));
					monthlyStatisticsDetail.setClassName(bClassVo.getClassName());
					monthlyStatisticsDetail.setClassCount(0L);
					List<ViolationApply> studentAttenceDetails = violations.get(bClassVo.getClassName());
					if (CollectionUtil.isNotEmpty(studentAttenceDetails)) {
						monthlyStatisticsDetail.setClassCount((long) studentAttenceDetails.size());
					}
					monthlyStatisticsDetails.add(monthlyStatisticsDetail);
				}
				break;
		}
		Collections.sort(monthlyStatisticsDetails, Comparator.comparingLong(MonthlyStatisticsDetail::getClassCount).reversed());
		
		return monthlyStatisticsDetails;
	}
	
	@Override
	public List<MonthlyStatisticsDetail> getMonthlyStudentDormitorySummary(String classId, String month, String operateType) {
		List<SdStudentAttenceDetail> dormitory = new ArrayList<>();
		List<MonthlyStatisticsDetail> details = new ArrayList<>();
		if (operateType.equals("dormitory")) {
			dormitory =  sdAttenceDao.getMonthlyAttenceStatisticsData(Collections.singletonList(Long.parseLong(classId)), month, "2");
			getAttenceDetails(dormitory, details);
		}
		
		if (operateType.equals("weekend")) {
			dormitory = sdAttenceDao.getMonthlyWeekendStatisticsData(Collections.singletonList(Long.parseLong(classId)), month, "2");
			getAttenceDetails(dormitory, details);
		}
		
		if (operateType.equals("retention")) {
			List<DormitoryRetention> retentions =  appRetentionService.getMonthlyStatisticsRetention(Collections.singletonList(Long.parseLong(classId)), month);
			Map<Long, List<DormitoryRetention>> collect = retentions.stream().collect(Collectors.groupingBy(DormitoryRetention::getStudentId));
			for (Map.Entry<Long, List<DormitoryRetention>> entry : collect.entrySet()) {
				MonthlyStatisticsDetail monthlyStatisticsDetail = new MonthlyStatisticsDetail();
				monthlyStatisticsDetail.setStudentId(String.valueOf(entry.getKey()));
				List<DormitoryRetention> attenceDetails = entry.getValue();
				monthlyStatisticsDetail.setStudentName(attenceDetails.get(0).getStudentName());
				if (CollectionUtil.isNotEmpty(attenceDetails)) {
					monthlyStatisticsDetail.setClassCount((long) attenceDetails.size());
				}
				details.add(monthlyStatisticsDetail);
			}
		}
		if (operateType.equals("morningExercises")) {
			List<MorningExercises> morningExercises = appMorningExercisesService.getMonthlyStatisticsMorningExercises(Collections.singletonList(Long.parseLong(classId)), month);
			Map<Long, List<MorningExercises>> collect = morningExercises.stream().collect(Collectors.groupingBy(MorningExercises::getStudentId));
			
			for (Map.Entry<Long, List<MorningExercises>> entry : collect.entrySet()) {
				MonthlyStatisticsDetail monthlyStatisticsDetail = new MonthlyStatisticsDetail();
				monthlyStatisticsDetail.setStudentId(String.valueOf(entry.getKey()));
				List<MorningExercises> attenceDetails = entry.getValue();
				monthlyStatisticsDetail.setStudentName(attenceDetails.get(0).getStudentName());
				if (CollectionUtil.isNotEmpty(attenceDetails)) {
					monthlyStatisticsDetail.setClassCount((long) attenceDetails.size());
				}
				details.add(monthlyStatisticsDetail);
			}
		}
		if (operateType.equals("patrol")) {
			List<ViolationPatrol> violationPatrols= violationPatrolDao.getMonthlyViolationCount(month, Collections.singletonList(Long.parseLong(classId)));
			Map<Long, List<ViolationPatrol>> collect = violationPatrols.stream().collect(Collectors.groupingBy(ViolationPatrol::getStudentId));
			
			for (Map.Entry<Long, List<ViolationPatrol>> entry : collect.entrySet()) {
				MonthlyStatisticsDetail monthlyStatisticsDetail = new MonthlyStatisticsDetail();
				monthlyStatisticsDetail.setStudentId(String.valueOf(entry.getKey()));
				List<ViolationPatrol> attenceDetails = entry.getValue();
				monthlyStatisticsDetail.setStudentName(attenceDetails.get(0).getStudentName());
				if (CollectionUtil.isNotEmpty(attenceDetails)) {
					monthlyStatisticsDetail.setClassCount((long) attenceDetails.size());
				}
				details.add(monthlyStatisticsDetail);
			}
		}
		if (operateType.equals("violation")) {
			List<ViolationApply> violationStatistics = violationApplyDao.getMonthlyViolationStatistics(month, Collections.singletonList(Long.parseLong(classId)));
			Map<String, List<ViolationApply>> collect = violationStatistics.stream().collect(Collectors.groupingBy(ViolationApply::getStudentId));
			for (Map.Entry<String, List<ViolationApply>> entry : collect.entrySet()) {
				MonthlyStatisticsDetail monthlyStatisticsDetail = new MonthlyStatisticsDetail();
				monthlyStatisticsDetail.setStudentId(String.valueOf(entry.getKey()));
				List<ViolationApply> attenceDetails = entry.getValue();
				monthlyStatisticsDetail.setStudentName(attenceDetails.get(0).getStudentName());
				if (CollectionUtil.isNotEmpty(attenceDetails)) {
					monthlyStatisticsDetail.setClassCount((long) attenceDetails.size());
				}
				details.add(monthlyStatisticsDetail);
			}
		}
		Collections.sort(details, Comparator.comparingLong(MonthlyStatisticsDetail::getClassCount).reversed());
		
		return details;
	}
	
	private void getAttenceDetails(List<SdStudentAttenceDetail> dormitory, List<MonthlyStatisticsDetail> details) {
		Map<String, List<SdStudentAttenceDetail>> collect = dormitory.stream().collect(Collectors.groupingBy(SdStudentAttenceDetail::getStudentId));
		for (Map.Entry<String, List<SdStudentAttenceDetail>> stringListEntry : collect.entrySet()) {
			MonthlyStatisticsDetail monthlyStatisticsDetail = new MonthlyStatisticsDetail();
			monthlyStatisticsDetail.setStudentId(stringListEntry.getKey());
			List<SdStudentAttenceDetail> attenceDetails = stringListEntry.getValue();
			monthlyStatisticsDetail.setStudentName(attenceDetails.get(0).getStudentName());
			if (CollectionUtil.isNotEmpty(attenceDetails)) {
				monthlyStatisticsDetail.setClassCount((long) attenceDetails.size());
			}
			details.add(monthlyStatisticsDetail);
		}
	}
	
	private List<BClassVo> getbClassVos(String userId) {
		boolean isDeptManager = false ; //是否部门经理
		List<Long> roleIdList = sysUserRoleService.listRoleIdByUserId(Long.valueOf(userId));
		for (Long roleId : roleIdList) {
			if(roleId == 2) {
				isDeptManager = true ;
				break;
			}
		}
		
		List<BClassVo> classList = new ArrayList<>();
		if(isDeptManager) {
			SysUser user = sysUserDao.selectById(userId);
			List<Long> deptIds = sysDeptDao.getAllChildByParent(user.getDeptId());
			//classList = classDao.getAppClassDeptByClaId(user.getDeptId());
			classList = bClassDao.getAppClassByDeptIds(deptIds);
		} else {
			// 获取班主任下所有班级
			classList = bClassDao.getAppClassListByTeaId(Long.valueOf(userId));
		}
		return classList;
	}
}
